package solutions.ferpa.ztest.ent;

import java.sql.*;
import java.util.ArrayList;
import br.com.telescope.adsrt.dom.*;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.t2.exception.Severity;
import br.com.telescope.util.TextUtil;
import br.com.telescope.util.DateUtil;
import br.com.telescope.util.FormatUtil;

/**
 * API de persistência de dados da entidade VAZAO_PREFIXO_SERIE
 * @author Gerado pelo Telescope
 */
public class EntVazaoPrefixoSerie extends Entity {
    
    public final static String ENTITY_NAME = "ZTEST.VAZAO_PREFIXO_SERIE";
    public final static String TABLE_NAME = "VAZAO_PREFIXO_SERIE";
    
    // <editor-fold defaultstate="collapsed" desc="Contrutores e inicializacao">
    /**
     * Construtores
     */
    public EntVazaoPrefixoSerie() {
        super();
        initialize();
    }
    
    public EntVazaoPrefixoSerie(BaseRuntime ctx) {
        super();
        initialize(ctx);
    }
    
    @Override
    public String getPrimaryKeyColumn() {
        return "ID";
    }
    
    @Override
    public void initialize(BaseRuntime ctx) {
        super.initialize(ctx);
        initialize();
    }
    
    public void initialize() {
        aId = new DomId(this,"ID", "Id"); 
        aId.setRequired(true);
        oId = new DomId();
        aVazaoNominal = new DomDouble(this,"VAZAO_NOMINAL", "Vazão nominal (m3/h)"); 
        aVazaoNominal.setRequired(true);
        oVazaoNominal = new DomDouble();
        aPrefixoNumeroSerie = new DomUpper(this,"PREFIXO_NUMERO_SERIE", "Prefixo para número de série"); 
        aPrefixoNumeroSerie.setRequired(true);
        oPrefixoNumeroSerie = new DomUpper();
        aAnoReferenciaSequencia = new DomInteger(this,"ANO_REFERENCIA_SEQUENCIA", "Ano referência (próxima sequência)"); 
        aAnoReferenciaSequencia.setRequired(true);
        oAnoReferenciaSequencia = new DomInteger();
        aProximaSequenciaProduto = new DomInteger(this,"PROXIMA_SEQUENCIA_PRODUTO", "Próxima sequência produto"); 
        aProximaSequenciaProduto.setRequired(true);
        oProximaSequenciaProduto = new DomInteger();
        ressetModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributos da entidade">
    
    // Id
    private DomId aId;
    private DomId oId;
    
    // Vazão nominal (m3/h)
    private DomDouble aVazaoNominal;
    private DomDouble oVazaoNominal;
    
    // Prefixo para número de série
    private DomUpper aPrefixoNumeroSerie;
    private DomUpper oPrefixoNumeroSerie;
    
    // Ano referência (próxima sequência)
    private DomInteger aAnoReferenciaSequencia;
    private DomInteger oAnoReferenciaSequencia;
    
    // Próxima sequência produto
    private DomInteger aProximaSequenciaProduto;
    private DomInteger oProximaSequenciaProduto;
    
    // <editor-fold defaultstate="collapsed" desc="Atributo ID">
    
    public EntVazaoPrefixoSerie id(Long value) {
        setId(value);
        return this;
    }
    
    public void setId(DomId value) {
        if (value == null || value.isNull()) {
            nullifyId();
        } else {
            aId.setValue(value.getValue());
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(String value) {
        if (value == null) {
            nullifyId();
        } else {
            aId.setValue(value);
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(Long value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void setId(Object value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyId() {
        if (!aId.isNull()) {
            aId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getId() {
        return aId;
    }
    
    public DomId oldId() {
        return oId;
    }
    
    public Long valueOfId() {
        return aId.getValue();
    }
    
    public boolean isIdModified() {
        return aId.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo VAZAO_NOMINAL">
    
    public EntVazaoPrefixoSerie vazaoNominal(Double value) {
        setVazaoNominal(value);
        return this;
    }
    
    public void setVazaoNominal(DomDouble value) {
        if (value == null || value.isNull()) {
            nullifyVazaoNominal();
        } else {
            aVazaoNominal.setValue(value.getValue());
            if (aVazaoNominal.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setVazaoNominal(String value) {
        if (value == null) {
            nullifyVazaoNominal();
        } else {
            aVazaoNominal.setValue(value);
            if (aVazaoNominal.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setVazaoNominal(Double value) {
        aVazaoNominal.setValue(value);
        if (aVazaoNominal.isModified()) {
            setModified(true);
        }
    }
    
    public void setVazaoNominal(Object value) {
        aVazaoNominal.setValue(value);
        if (aVazaoNominal.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyVazaoNominal() {
        if (!aVazaoNominal.isNull()) {
            aVazaoNominal.setNull(true);
            setModified(true);
        }
    }
    
    public DomDouble getVazaoNominal() {
        return aVazaoNominal;
    }
    
    public DomDouble oldVazaoNominal() {
        return oVazaoNominal;
    }
    
    public Double valueOfVazaoNominal() {
        return aVazaoNominal.getValue();
    }
    
    public boolean isVazaoNominalModified() {
        return aVazaoNominal.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo PREFIXO_NUMERO_SERIE">
    
    public EntVazaoPrefixoSerie prefixoNumeroSerie(String value) {
        setPrefixoNumeroSerie(value);
        return this;
    }
    
    public void setPrefixoNumeroSerie(DomUpper value) {
        if (value == null || value.isNull()) {
            nullifyPrefixoNumeroSerie();
        } else {
            aPrefixoNumeroSerie.setValue(value.getValue());
            if (aPrefixoNumeroSerie.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setPrefixoNumeroSerie(String value) {
        if (value == null) {
            nullifyPrefixoNumeroSerie();
        } else {
            aPrefixoNumeroSerie.setValue(value);
            if (aPrefixoNumeroSerie.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setPrefixoNumeroSerie(Object value) {
        aPrefixoNumeroSerie.setValue(value);
        if (aPrefixoNumeroSerie.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyPrefixoNumeroSerie() {
        if (!aPrefixoNumeroSerie.isNull()) {
            aPrefixoNumeroSerie.setNull(true);
            setModified(true);
        }
    }
    
    public DomUpper getPrefixoNumeroSerie() {
        return aPrefixoNumeroSerie;
    }
    
    public DomUpper oldPrefixoNumeroSerie() {
        return oPrefixoNumeroSerie;
    }
    
    public String valueOfPrefixoNumeroSerie() {
        return aPrefixoNumeroSerie.getValue();
    }
    
    public boolean isPrefixoNumeroSerieModified() {
        return aPrefixoNumeroSerie.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo ANO_REFERENCIA_SEQUENCIA">
    
    public EntVazaoPrefixoSerie anoReferenciaSequencia(Integer value) {
        setAnoReferenciaSequencia(value);
        return this;
    }
    
    public void setAnoReferenciaSequencia(DomInteger value) {
        if (value == null || value.isNull()) {
            nullifyAnoReferenciaSequencia();
        } else {
            aAnoReferenciaSequencia.setValue(value.getValue());
            if (aAnoReferenciaSequencia.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setAnoReferenciaSequencia(String value) {
        if (value == null) {
            nullifyAnoReferenciaSequencia();
        } else {
            aAnoReferenciaSequencia.setValue(value);
            if (aAnoReferenciaSequencia.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setAnoReferenciaSequencia(Integer value) {
        aAnoReferenciaSequencia.setValue(value);
        if (aAnoReferenciaSequencia.isModified()) {
            setModified(true);
        }
    }
    
    public void setAnoReferenciaSequencia(Object value) {
        aAnoReferenciaSequencia.setValue(value);
        if (aAnoReferenciaSequencia.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyAnoReferenciaSequencia() {
        if (!aAnoReferenciaSequencia.isNull()) {
            aAnoReferenciaSequencia.setNull(true);
            setModified(true);
        }
    }
    
    public DomInteger getAnoReferenciaSequencia() {
        return aAnoReferenciaSequencia;
    }
    
    public DomInteger oldAnoReferenciaSequencia() {
        return oAnoReferenciaSequencia;
    }
    
    public Integer valueOfAnoReferenciaSequencia() {
        return aAnoReferenciaSequencia.getValue();
    }
    
    public boolean isAnoReferenciaSequenciaModified() {
        return aAnoReferenciaSequencia.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo PROXIMA_SEQUENCIA_PRODUTO">
    
    public EntVazaoPrefixoSerie proximaSequenciaProduto(Integer value) {
        setProximaSequenciaProduto(value);
        return this;
    }
    
    public void setProximaSequenciaProduto(DomInteger value) {
        if (value == null || value.isNull()) {
            nullifyProximaSequenciaProduto();
        } else {
            aProximaSequenciaProduto.setValue(value.getValue());
            if (aProximaSequenciaProduto.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setProximaSequenciaProduto(String value) {
        if (value == null) {
            nullifyProximaSequenciaProduto();
        } else {
            aProximaSequenciaProduto.setValue(value);
            if (aProximaSequenciaProduto.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setProximaSequenciaProduto(Integer value) {
        aProximaSequenciaProduto.setValue(value);
        if (aProximaSequenciaProduto.isModified()) {
            setModified(true);
        }
    }
    
    public void setProximaSequenciaProduto(Object value) {
        aProximaSequenciaProduto.setValue(value);
        if (aProximaSequenciaProduto.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyProximaSequenciaProduto() {
        if (!aProximaSequenciaProduto.isNull()) {
            aProximaSequenciaProduto.setNull(true);
            setModified(true);
        }
    }
    
    public DomInteger getProximaSequenciaProduto() {
        return aProximaSequenciaProduto;
    }
    
    public DomInteger oldProximaSequenciaProduto() {
        return oProximaSequenciaProduto;
    }
    
    public Integer valueOfProximaSequenciaProduto() {
        return aProximaSequenciaProduto.getValue();
    }
    
    public boolean isProximaSequenciaProdutoModified() {
        return aProximaSequenciaProduto.isModified();
    }
    // </editor-fold>
    // </editor-fold>
    
    @Override
    protected void processDeleteRestrict() throws AdsException {
        // Nullify cascade ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_PERMANENTE
        {
            EntModeloHidrometro external = new EntModeloHidrometro(ctx);
            external.findByVazaoPermanente(valueOfId());
            if (external.next()) {
                throw new AdsException("ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_PERMANENTE.RESTRICTED",
                        AdsException.ERROR,
                        "Não pode excluir porque existem Modelos de hidrômetros fazendo referencia para este registro");
            }
            external.close();
        }
        // Nullify cascade ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_HIDROMETRO
        {
            EntModeloHidrometro external = new EntModeloHidrometro(ctx);
            external.findByVazaoPrefixoSerie(valueOfId());
            if (external.next()) {
                throw new AdsException("ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_HIDROMETRO.RESTRICTED",
                        AdsException.ERROR,
                        "Não pode excluir porque existem Modelos de hidrômetros fazendo referencia para este registro");
            }
            external.close();
        }
    }
    
    // <editor-fold defaultstate="collapsed" desc="getErrors">
    /**
     * Traduz um erro recebido do banco de dados para um AdsException
     */
    @Override
    public AdsException getErrors(String errorMsg, int transaction) {
        AdsException e;
        String msg = errorMsg.toUpperCase();
        
        if (transaction == DELETE_TRANSACTION) {
            if (msg.indexOf("FK_MODHID_VAZAO_PERMANENTE") >= 0) {
                e = new AdsException("ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_PERMANENTE.RESTRICTED", 
                        Severity.ERROR,
                        "Não pode excluir porque existem Modelos de hidrômetros fazendo referencia para este registro! (FK_MODHID_VAZAO_PERMANENTE)");
                return e;
            } else if (msg.indexOf("FK_MODHID_VAZAO_HIDROMETRO") >= 0) {
                e = new AdsException("ZTEST.MODELO_HIDROMETRO.FK_MODHID_VAZAO_HIDROMETRO.RESTRICTED", 
                        Severity.ERROR,
                        "Não pode excluir porque existem Modelos de hidrômetros fazendo referencia para este registro! (FK_MODHID_VAZAO_HIDROMETRO)");
                return e;
            } else {
                e = new AdsException("ZTEST.VAZAO_PREFIXO_SERIE.GET_ERRORS_UNKNOWN",
                        AdsException.UNKNOWN,
                        "Erro não esperado: " + errorMsg);
            }
        } else {
            if (msg.indexOf("UK_VAPRSE_VAZAO") >= 0) {
                e = new AdsException("ZTEST.VAZAO_PREFIXO_SERIE.UK_VAPRSE_VAZAO", 
                        Severity.ERROR,
                        "Registro duplicado! A vazão nominal deve ser única! Vazão nominal (m3/h) ${VAZAO_NOMINAL} (UK_VAPRSE_VAZAO)");
                return e;
            } else if (msg.indexOf("PK_VAPRSE") >= 0) {
                e = new AdsException("ZTEST.VAZAO_PREFIXO_SERIE.PK_VAPRSE", 
                        Severity.ERROR,
                        "ID duplicado! (PK_VAPRSE)");
                return e;
            } else {
                e = new AdsException("ZTEST.VAZAO_PREFIXO_SERIE.GET_ERRORS_UNKNOWN",
                        AdsException.UNKNOWN,
                        "Erro não esperado: " + errorMsg);
            }
        }
        return e;
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Entity Information">
    
    public String getEntityName() {
        return ENTITY_NAME;
    }
    
    public String getTableName() {
        return TABLE_NAME;
    }
    
    public String idSequenceName() {
        return "PK_SEQUENCE";
    }
    
    private ArrayList<Field> allAttributes;
    public ArrayList<Field> getAllAttributes() {
        if (allAttributes == null) {
            allAttributes = new ArrayList<Field>();
            allAttributes.add(aId);
            allAttributes.add(aVazaoNominal);
            allAttributes.add(aPrefixoNumeroSerie);
            allAttributes.add(aAnoReferenciaSequencia);
            allAttributes.add(aProximaSequenciaProduto);
        }
        return allAttributes;
    }
    
    /**
     * Retorna o valor da primeira UK da entidade
     * Se ela for composta, retorna a concatenação de toda a combinação
     * de atributos separados por um espaço.
     */
    public String valueOfUk() {
        return getVazaoNominal().toString();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Relationships">
    
    
    public void findByVazaoNominal(double vazaoNominal) throws AdsException {
        findBy(new String[] {"VAZAO_NOMINAL"},
                new Object[] {vazaoNominal});
    }
    /**
     * Retorna os registros de MODELO_HIDROMETRO que referenciam este registro através do atributo VAZAO_PERMANENTE_ID
     */
    public EntModeloHidrometro findAllModeloHidrometroVazaoPermanente() throws AdsException {
        return findAllModeloHidrometroVazaoPermanente("order by ID");
    }
    
    /**
     * Retorna os registros de MODELO_HIDROMETRO que referenciam este registro através do atributo VAZAO_PERMANENTE_ID
     */
    public EntModeloHidrometro findAllModeloHidrometroVazaoPermanente(String sqlAppend) throws AdsException {
        EntModeloHidrometro out = new EntModeloHidrometro(ctx);
        out.find("select ID from MODELO_HIDROMETRO where VAZAO_PERMANENTE_ID = " + valueOfId() + " " + sqlAppend);
        return out;
    }
    
    /**
     * Retorna os registros de MODELO_HIDROMETRO que referenciam este registro através do atributo VAZAO_PREFIXO_SERIE_ID
     */
    public EntModeloHidrometro findAllModeloHidrometroVazaoPrefixoSerie() throws AdsException {
        return findAllModeloHidrometroVazaoPrefixoSerie("order by ID");
    }
    
    /**
     * Retorna os registros de MODELO_HIDROMETRO que referenciam este registro através do atributo VAZAO_PREFIXO_SERIE_ID
     */
    public EntModeloHidrometro findAllModeloHidrometroVazaoPrefixoSerie(String sqlAppend) throws AdsException {
        EntModeloHidrometro out = new EntModeloHidrometro(ctx);
        out.find("select ID from MODELO_HIDROMETRO where VAZAO_PREFIXO_SERIE_ID = " + valueOfId() + " " + sqlAppend);
        return out;
    }
    
    
    /**
     * Método que copia os valores dos atributos
     * para os valores respectivos old 
     */
    public void saveOldAtributes() {
        oVazaoNominal.setValue(aVazaoNominal);
        oProximaSequenciaProduto.setValue(aProximaSequenciaProduto);
        oAnoReferenciaSequencia.setValue(aAnoReferenciaSequencia);
        oPrefixoNumeroSerie.setValue(aPrefixoNumeroSerie);
        oId.setValue(aId);
    }
    
    /**
     * Método que retorna as regras da entidade
     * @return ArrayList com as regras ou null caso não existir nenhuma regra
     */
    public ArrayList getAllRules() {
        ArrayList<EntityRule> out = new ArrayList<EntityRule>();
        {
            PrimaryKeyRule rule = new PrimaryKeyRule();
            rule.setEntity(EntVazaoPrefixoSerie.class);
            rule.setName("PK_VAPRSE");
            rule.setPkAttribute(new DomId("ID",""));
            out.add(rule);
        }
        {
            UniqueKeyRule rule = new UniqueKeyRule();
            rule.setEntity(EntVazaoPrefixoSerie.class);
            rule.setName("UK_VAPRSE_VAZAO");
            rule.addAttribute(new DomDouble("VAZAO_NOMINAL",""));
            out.add(rule);
        }
        return out;
    }
    // </editor-fold>
    
    @Override
    protected void preInsert() throws AdsException {
        calcularAnoProximaSequencia(); //Calcular ano e próxima sequência
    }
    
    @Override
    protected void preUpdate() throws AdsException {
        calcularAnoProximaSequencia(); //Calcular ano e próxima sequência
    }
    
    @Override
    public void fillDefaultValues() throws AdsException {
        if (aId.isNull()) {
            aId.setValue("" + ctx.getNextVal("pk_sequence"));
        }
    }
    
    // <editor-fold defaultstate="collapsed" desc="Métodos customizados">
    
    /**
     * Calcular a identificação do hidrometro.
     */
    public String calcularIdentificacaoHidrometro() throws AdsException {
        // <user-code id="21877635" parentId="21877623" hashcode="-326d61e8" length="1484">
        // import br.com.telescope.util.TextUtil;
        
        getProximaSequenciaProduto().add(1);
        upd();
            
        String out = valueOfPrefixoNumeroSerie()
                + getAnoReferenciaSequencia().toText()
                + ctx.getPreference(ENTITY_NAME + ".SIGLA_MARCA_NUMERO_SERIE","Z")
                + getVazaoNominal().toText()
                + FormatUtil.mask(
                        valueOfProximaSequenciaProduto().doubleValue(), 
                        TextUtil.leftZero("0", 
                                ctx.getPreferenceInteger(ENTITY_NAME + ".QTDE_DIGITOS_NUMERO_SERIE",6)))
                ;
        /*
        EntModeloHidrometro modeloBase = findModeloHidrometro();
        
        EntTipoModeloHidrometro tipoModelo = modeloBase.findTipoModeloHidrometro();
        
        tipoModelo.getProximaSequenciaProduto().add(1);
        tipoModelo.upd();
        
        // - A identicação dos hidroômetros deve ser feita na aprovação para os aprovados.
        // - O hidrômetro tem um serial identicado por uma letra a sua capacidade. (alfanumérico).
        String codigo = tipoModelo.valueOfPrefixoNumeroSerie();
        
        // Anos (2 dígitos)
        codigo += FormatUtil.mask(DateUtil.getToday(), "YY");
        
        // - Cada Qn tem uma vazão nominal.  Exemplo A = vazão (QN),  2 dígitos para o ano,  Fabricante (Z).
        codigo += modeloBase.findTipoModeloHidrometro().getVazaoNominal().toText();
        
        // - Faixa de número serial por modelo (o número tem 6 dígitos podendo aumentar) 10 dígitos.
        codigo += FormatUtil.mask(tipoModelo.valueOfProximaSequenciaProduto().doubleValue(), "0000000");
        
        modeloBase.close();
        */
        
        return out;
        // </user-code>
    }
    
    /**
     * Regra de ação: Calcular ano e próxima sequência
     */
    private void calcularAnoProximaSequencia() throws AdsException {
        // <user-code id="21877987" parentId="21877961" hashcode="-3eb8c166" length="349">
        // import br.com.telescope.util.DateUtil;
        // import br.com.telescope.util.FormatUtil;
        
        int anoCorrente = Integer.parseInt(FormatUtil.mask(DateUtil.getToday(), "YY"));
        if (getAnoReferenciaSequencia().isNull() || (anoCorrente > valueOfAnoReferenciaSequencia())) {
            setAnoReferenciaSequencia(anoCorrente);
            setProximaSequenciaProduto(1);
        }
        // </user-code>
    }
}
